/**
 * 
 */
package com.cea.papyrus.diagram.component;

import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
import org.eclipse.uml2.uml.Abstraction;
import org.eclipse.uml2.uml.Artifact;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.CollaborationUse;
import org.eclipse.uml2.uml.Comment;
import org.eclipse.uml2.uml.Component;
import org.eclipse.uml2.uml.Connector;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.DataType;
import org.eclipse.uml2.uml.Dependency;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Enumeration;
import org.eclipse.uml2.uml.EnumerationLiteral;
import org.eclipse.uml2.uml.Generalization;
import org.eclipse.uml2.uml.InstanceSpecification;
import org.eclipse.uml2.uml.Interface;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Port;
import org.eclipse.uml2.uml.PrimitiveType;
import org.eclipse.uml2.uml.Realization;
import org.eclipse.uml2.uml.Usage;

import com.cea.papyrus.core.editor.EditpartFactoryBase;
import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.AnchorEditPart;
import com.cea.papyrus.core.editpart.GraphEdgeEditPart;
import com.cea.papyrus.core.editpart.GraphNodeWithSemanticEditPart;
import com.cea.papyrus.core.editpart.NodeNameDisplayEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.AbstractionEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.AssociationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ClassEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.CommentEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ConstraintEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.DataTypeEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.DependencyEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.EnumerationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.EnumerationLiteralEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.GeneralizationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.LinkInstanceSpecificationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.PrimitiveTypeEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.RealizationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.UsageEditPart;
import com.cea.papyrus.diagram.component.editpart.ArtifactEditPart;
import com.cea.papyrus.diagram.component.editpart.ComponentDiagramEditPart;
import com.cea.papyrus.diagram.component.editpart.ComponentEditPart;
import com.cea.papyrus.diagram.component.editpart.ConnectorEditPart;
import com.cea.papyrus.diagram.component.editpart.InterfaceGraphEdgeEditPart;
import com.cea.papyrus.diagram.component.editpart.PackageEditPart;
import com.cea.papyrus.diagram.component.editpart.PortEditPart;
import com.cea.papyrus.diagram.component.editpart.PortNameEditPart;
import com.cea.papyrus.diagram.composite.editpart.RoleBindingEditPart;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.DiagramElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphEdge;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * * Manages creation of controllers for component diagram elements.
 * 
 * @author al090761
 *
 */
public class ComponentDiagramGraphicalEditPartsFactory extends EditpartFactoryBase implements
EditPartFactory, IComponentDiagramPropertyValue {

	/**
	 * The model manager.
	 */
	protected ModelManager modelManager;

	/**
	 * The Constructor.
	 * 
	 * @param modelManager the model manager
	 */
	public ComponentDiagramGraphicalEditPartsFactory(ModelManager modelManager) {
		this.modelManager = modelManager;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.gef.EditPartFactory#createEditPart(org.eclipse.gef.EditPart, java.lang.Object)
	 */
	public EditPart createEditPart(EditPart context, Object obj) {
		
		//new mechanism
		EditPart result= getEditPartFromProperty(context, obj,modelManager);
		if (result!=null){
			return result;
		}
		
		//to identify the good editpart we need the nature of the object graphEdge or graphNode and
		// uml Elment connected
		//case of a diagram
		if (obj instanceof Diagram) {
			return new ComponentDiagramEditPart((Diagram)obj,modelManager);
		} else if(obj instanceof GraphNode){
			if ((((GraphNode)obj).getSemanticParent()==null) &&(((Uml1SemanticModelBridge)((GraphNode)obj).getSemanticModel())==null) ){
				return new AnchorEditPart((GraphNode)obj,modelManager);}
			if ((((GraphNode)obj).getSemanticParent()!=null) &&
					(((Uml1SemanticModelBridge)((GraphNode)obj).getSemanticModel())==null)&&
					((Uml1SemanticModelBridge)((GraphElement)((GraphNode)obj).getSemanticParent()).getSemanticModel()).getElement() instanceof Port){
				return new PortNameEditPart((GraphNode)obj,modelManager);}
			if ((((GraphNode)obj).getSemanticParent()!=null) &&
					(((Uml1SemanticModelBridge)((GraphNode)obj).getSemanticModel())==null)&&
					((Uml1SemanticModelBridge)((GraphElement)((GraphNode)obj).getSemanticParent()).getSemanticModel()).getElement() instanceof Component){
				return new ComponentEditPart((GraphNode)obj,modelManager);}
			if ((((GraphNode)obj).getSemanticParent()!=null) &&
					(((Uml1SemanticModelBridge)((GraphNode)obj).getSemanticModel())==null)&&
					((Uml1SemanticModelBridge)((GraphElement)((GraphNode)obj).getSemanticParent()).getSemanticModel()).getElement() instanceof Artifact){
				return new ArtifactEditPart((GraphNode)obj,modelManager);}
			if ((((GraphNode)obj).getSemanticParent()!=null) &&
					(((Uml1SemanticModelBridge)((GraphNode)obj).getSemanticModel())==null)&&
					((Uml1SemanticModelBridge)((GraphElement)((GraphNode)obj).getSemanticParent()).getSemanticModel()).getElement() instanceof Package){
				return new PackageEditPart((GraphNode)obj,modelManager);}		
			if ((((GraphNode)obj).getSemanticParent()!=null) &&
					(((Uml1SemanticModelBridge)((GraphNode)obj).getSemanticModel())==null)&&
					((Uml1SemanticModelBridge)((GraphElement)((GraphNode)obj).getSemanticParent()).getSemanticModel()).getElement() instanceof Interface){
				Element umlSemanticParent= ((Uml1SemanticModelBridge)((GraphElement)((GraphNode) obj).getSemanticParent()).getSemanticModel()).getElement();
				return new NodeNameDisplayEditPart((GraphNode)obj,umlSemanticParent,modelManager);}
			if ((((Uml1SemanticModelBridge)((GraphNode)obj).getSemanticModel()).getElement())==null){
				return new GraphNodeWithSemanticEditPart((GraphNode)obj,modelManager);}

			Element elt =((Uml1SemanticModelBridge)((GraphNode)obj).getSemanticModel()).getElement();
			return searchEditPart((GraphNode)obj, elt);
		}

		//case of a graphEdge
		else if (obj instanceof GraphEdge){
			if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel())!=null){
				if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Generalization){
					return new GeneralizationEditPart((GraphEdge)obj,modelManager);}
				if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Association){
					return new AssociationEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Usage){
					return new UsageEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Realization){
					return new RealizationEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Abstraction){
					return new AbstractionEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Dependency){
					return new DependencyEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Connector){
					return new ConnectorEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof InstanceSpecification){
					return new LinkInstanceSpecificationEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof CollaborationUse){
					return new RoleBindingEditPart((GraphEdge)obj,modelManager);}
			}
			else{
				
				GraphEdge ge=(GraphEdge)obj;
				if (ge.getSemanticParent()!=null){
					return new InterfaceGraphEdgeEditPart(ge,modelManager);
				}
				return new GraphEdgeEditPart(ge, modelManager);		
			}
		}

		return null;
	}


	/**
	 * Add Specific behavior for this diagram.
	 */
	@Override
	   public  EditPart getEditPartFromProperty(EditPart context, Object obj, ModelManager modelManager){
	        if(obj instanceof DiagramElement){
	            //look for the value of editpart
	            DiagramElement di2elt= (DiagramElement)obj;
	            String editPartName=di2elt.getEditpartName();
	            if(COMPONENTDIAGRAM_NODE_COMPONENT.equals(editPartName)) {
	              return new com.cea.papyrus.diagram.component.editpart.ComponentEditPart((GraphNode)di2elt,modelManager); 
	          }
	          else if(CLASSDIAGRAM_NODE_COMPONENT.equals(editPartName)) {
	              return new com.cea.papyrus.diagram.classdiagram.editpart.ComponentEditPart((GraphNode)di2elt,modelManager); 
	          }
	            else{return null;}
	        }
	        else {return null;}
	        
	   }
	
	/**
	 * Search edit part.
	 * 
	 * @param graphNode the graph node
	 * @param elt the elt
	 * 
	 * @return the edit part
	 */
	public EditPart searchEditPart(GraphNode graphNode, Element elt) {
		// Component
		if (elt instanceof org.eclipse.uml2.uml.Component){
			return new ComponentEditPart(graphNode, modelManager);
		}
		// Artifact
		if (elt instanceof org.eclipse.uml2.uml.Artifact){
			return new ArtifactEditPart(graphNode, modelManager);
		}
		//Package
		if (elt instanceof org.eclipse.uml2.uml.Package){
			return new PackageEditPart(graphNode, modelManager);
		}
		// Port
		if (elt instanceof org.eclipse.uml2.uml.Port){
			return new PortEditPart(graphNode, modelManager);
		}
		
		// Enumeration Literal
		if (elt instanceof EnumerationLiteral) {
			return new EnumerationLiteralEditPart(graphNode, modelManager);
		}
		// Instance specification
		if (elt instanceof org.eclipse.uml2.uml.InstanceSpecification){
			return new com.cea.papyrus.diagram.classdiagram.editpart.InstanceSpecificationEditPart(graphNode, modelManager);
		}
		if (elt instanceof org.eclipse.uml2.uml.Slot){
			return new com.cea.papyrus.diagram.classdiagram.editpart.SlotEditPart(graphNode, modelManager);
		}
//		if (elt instanceof org.eclipse.uml2.uml.InstanceSpecification){
//		return new com.cea.papyrus.diagram.composite.editpart.InstanceSpecificationClassEditPart(graphNode, modelManager);
//		}
//		if (elt instanceof org.eclipse.uml2.uml.Slot){
//		return new CompositeSlotEditPart(graphNode, modelManager);
//		}
		if (elt instanceof org.eclipse.uml2.uml.Interface){
			return new com.cea.papyrus.diagram.component.editpart.InterfaceEditPart(graphNode, modelManager);
		}
		// Property
		if (elt instanceof org.eclipse.uml2.uml.Property){
			return new com.cea.papyrus.diagram.classdiagram.editpart.PropertyEditPart(graphNode,modelManager);
		}

		//Class
		if (elt instanceof org.eclipse.uml2.uml.Class){
			return new ClassEditPart(graphNode, modelManager);
		}

		// Comment
		if (elt instanceof Comment){
			return new CommentEditPart(graphNode, modelManager);
		}

		// Constraint
		if (elt instanceof Constraint){
			return new ConstraintEditPart(graphNode, modelManager);
		}
		// Primitive Type
		if (elt instanceof PrimitiveType) {
			return new PrimitiveTypeEditPart(graphNode, modelManager);
		}
		// Enumeration
		if (elt instanceof Enumeration) {
			return new EnumerationEditPart(graphNode, modelManager);
		}
		// DataType
		if (elt instanceof DataType) {
			return new DataTypeEditPart(graphNode, modelManager);
		}
		// Enumeration Literal
		if (elt instanceof EnumerationLiteral) {
			return new EnumerationLiteralEditPart(graphNode, modelManager);
		}
		return null;
	}

}
